"""
Command line interface for md2ppt.
"""

import argparse
import sys
from pathlib import Path
from typing import Optional

from ..parser.md_parser import MarkdownParser
from ..converter.ppt_builder import PPTBuilder
from ..utils.exceptions import MD2PPTError


class CLICommands:
    """Command line interface handler."""
    
    def __init__(self):
        self.parser = self._create_argument_parser()
    
    def _create_argument_parser(self) -> argparse.ArgumentParser:
        """Create and configure the argument parser."""
        parser = argparse.ArgumentParser(
            prog='md2ppt',
            description='Convert Markdown files to PowerPoint presentations',
            epilog='Example: md2ppt presentation.md -o slides.pptx --theme blue'
        )
        
        # Server mode arguments
        parser.add_argument(
            '--api',
            action='store_true',
            help='Start API server mode'
        )
        
        parser.add_argument(
            '--mcp',
            action='store_true',
            help='Start MCP server mode'
        )
        
        # Required arguments (optional in server modes)
        parser.add_argument(
            'input_file',
            nargs='?',
            help='Input Markdown file path'
        )
        
        # Optional arguments
        parser.add_argument(
            '-o', '--output',
            help='Output PowerPoint file path (default: same name as input with .pptx extension)',
            default=None
        )
        
        parser.add_argument(
            '--theme',
            choices=['default', 'blue', 'dark', 'green', 'red'],
            default='default',
            help='Presentation theme (default: default)'
        )
        
        parser.add_argument(
            '--image-width-ratio',
            type=float,
            default=0.7,
            help='Maximum image width as ratio of slide width (default: 0.7)'
        )
        
        # New v2 features
        parser.add_argument(
            '--format',
            choices=['pptx', 'html', 'video', 'all'],
            default='pptx',
            help='Output format (default: pptx)'
        )
        
        parser.add_argument(
            '--enable-animations',
            action='store_true',
            help='Enable animation support in output'
        )
        
        parser.add_argument(
            '--animation-engine',
            choices=['aspose', 'reveal', 'auto'],
            default='auto',
            help='Animation engine to use (default: auto)'
        )
        
        parser.add_argument(
            '--generate-tts',
            action='store_true',
            help='Generate TTS narration for video/audio output'
        )
        
        parser.add_argument(
            '--tts-voice',
            default='zh-CN-XiaoxiaoNeural',
            help='TTS voice ID (default: zh-CN-XiaoxiaoNeural)'
        )
        
        parser.add_argument(
            '--video-platform',
            choices=['youtube', 'tiktok', 'bilibili', 'wechat_video', '4k'],
            default='youtube',
            help='Video platform preset (default: youtube)'
        )
        
        parser.add_argument(
            '--background-music',
            help='Background music file for video output'
        )
        
        parser.add_argument(
            '--create-preview',
            action='store_true',
            help='Create a preview video (30s max)'
        )
        
        parser.add_argument(
            '-v', '--verbose',
            action='store_true',
            help='Enable verbose output'
        )
        
        parser.add_argument(
            '--version',
            action='version',
            version='md2ppt 0.1.0'
        )
        
        return parser
    
    def run(self, args: Optional[list] = None) -> int:
        """Run the CLI with given arguments."""
        try:
            # Parse arguments
            parsed_args = self.parser.parse_args(args)
            
            # Handle server modes
            if parsed_args.api:
                return self._start_api_server(parsed_args)
            elif parsed_args.mcp:
                return self._start_mcp_server(parsed_args)
            
            # Validate input file for conversion mode
            if not parsed_args.input_file:
                print("Error: input_file is required for conversion mode", file=sys.stderr)
                return 1
                
            input_path = Path(parsed_args.input_file)
            if not input_path.exists():
                print(f"Error: Input file not found: {input_path}", file=sys.stderr)
                return 1
            
            if input_path.suffix.lower() != '.md':
                print(f"Warning: Input file does not have .md extension: {input_path}")
            
            # Determine output path
            output_path = self._get_output_path(input_path, parsed_args.output)
            
            if parsed_args.verbose:
                print(f"Input file: {input_path}")
                print(f"Output file: {output_path}")
                print(f"Theme: {parsed_args.theme}")
            
            # Convert Markdown based on format
            if parsed_args.format == 'all':
                # Generate all formats
                self._convert_all_formats(
                    input_path=input_path,
                    output_path=output_path,
                    args=parsed_args
                )
            else:
                # Generate specific format
                self._convert_file(
                    input_path=input_path,
                    output_path=output_path,
                    args=parsed_args
                )
            
            print(f"Successfully created presentation: {output_path}")
            return 0
            
        except MD2PPTError as e:
            print(f"Error: {e}", file=sys.stderr)
            return 1
        except KeyboardInterrupt:
            print("\nOperation cancelled by user", file=sys.stderr)
            return 1
        except Exception as e:
            print(f"Unexpected error: {e}", file=sys.stderr)
            if parsed_args.verbose if 'parsed_args' in locals() else False:
                import traceback
                traceback.print_exc()
            return 1
    
    def _should_use_aspose_engine(self, args) -> bool:
        """Determine whether to use Aspose.Slides engine."""
        if args.animation_engine == 'aspose':
            return True
        elif args.animation_engine == 'reveal':
            return False
        else:  # auto
            # Use Aspose if animations are enabled and format is PPTX
            return args.enable_animations and hasattr(args, 'format') and args.format == 'pptx'
    
    def _get_output_path(self, input_path: Path, output_arg: Optional[str]) -> Path:
        """Determine the output file path."""
        if output_arg:
            return Path(output_arg)
        else:
            # Use input filename with .pptx extension
            return input_path.with_suffix('.pptx')
    
    def _convert_file(self, input_path: Path, output_path: Path, args) -> None:
        """Convert a Markdown file based on specified format."""
        
        if args.verbose:
            print(f"Converting to {args.format} format...")
        
        # Parse Markdown with animation support if enabled
        parser = MarkdownParser(enable_animations=args.enable_animations)
        try:
            doc_structure = parser.parse_file(str(input_path))
        except Exception as e:
            raise MD2PPTError(f"Failed to parse Markdown file: {e}")
        
        if args.verbose:
            print(f"Found {len(doc_structure.sections)} sections")
            print(f"Title: {doc_structure.title}")
            
        # Convert based on format
        if args.format == 'pptx':
            self._convert_to_pptx(doc_structure, output_path, args)
        elif args.format == 'html':
            self._convert_to_html(doc_structure, output_path, args)
        elif args.format == 'video':
            import asyncio
            asyncio.run(self._convert_to_video(doc_structure, output_path, args))
    
    def _convert_to_pptx(self, doc_structure, output_path: Path, args) -> None:
        """Convert to PowerPoint format."""
        if args.verbose:
            print("Building PowerPoint presentation...")
        
        # Choose animation engine based on settings
        use_aspose = self._should_use_aspose_engine(args)
        
        if use_aspose:
            if args.verbose:
                print("Using Aspose.Slides engine for enhanced animations...")
            
            try:
                from ..converter.aspose_ppt_builder import AsposePPTBuilder
                builder = AsposePPTBuilder(
                    theme_name=args.theme, 
                    enable_animations=args.enable_animations
                )
            except ImportError:
                if args.verbose:
                    print("Aspose.Slides not available, falling back to python-pptx...")
                builder = PPTBuilder(theme_name=args.theme)
        else:
            if args.verbose:
                print("Using python-pptx engine...")
            builder = PPTBuilder(theme_name=args.theme)
        
        # Update image width ratio if specified
        if args.image_width_ratio != 0.7:  # If not default
            builder.theme_manager.styles.IMAGE_MAX_WIDTH_RATIO = args.image_width_ratio
        
        try:
            presentation = builder.build_from_structure(doc_structure)
            
            # Animation info
            if hasattr(builder, 'get_animation_info'):
                anim_info = builder.get_animation_info()
                if args.verbose and anim_info.get('available'):
                    supported = anim_info.get('supported_animations', [])
                    print(f"Animation engine: {anim_info.get('engine', 'Unknown')}")
                    print(f"Supported animations: {len(supported)} types")
            
        except Exception as e:
            raise MD2PPTError(f"Failed to build presentation: {e}")
        
        # Save presentation
        if args.verbose:
            print(f"Saving presentation to {output_path}...")
        
        try:
            output_path.parent.mkdir(parents=True, exist_ok=True)
            builder.save(str(output_path))
        except Exception as e:
            raise MD2PPTError(f"Failed to save presentation: {e}")
    
    def _convert_to_html(self, doc_structure, output_path: Path, args) -> None:
        """Convert to HTML format."""
        if args.verbose:
            print("Generating HTML presentation...")
        
        from ..export.formats.html_exporter import HTMLExporter
        
        try:
            exporter = HTMLExporter(theme=args.theme)
            output_path.parent.mkdir(parents=True, exist_ok=True)
            exporter.export(doc_structure, str(output_path))
        except Exception as e:
            raise MD2PPTError(f"Failed to generate HTML: {e}")
    
    async def _convert_to_video(self, doc_structure, output_path: Path, args) -> None:
        """Convert to video format."""
        if args.verbose:
            print("Generating video presentation...")
        
        try:
            from ..export.formats.video_exporter import VideoExporter
            from ..audio.tts.edge_tts import TTSConfig
            
            # Create TTS config if narration is enabled
            tts_config = None
            if args.generate_tts:
                tts_config = TTSConfig(voice_id=args.tts_voice)
            
            # Create video exporter with platform preset
            exporter = VideoExporter(
                video_config=VideoExporter().create_video_config_preset(args.video_platform),
                tts_config=tts_config,
                html_theme=args.theme
            )
            
            output_path.parent.mkdir(parents=True, exist_ok=True)
            
            results = await exporter.export(
                doc_structure=doc_structure,
                output_path=str(output_path),
                generate_narration=args.generate_tts,
                background_music=args.background_music,
                create_preview=args.create_preview
            )
            
            if args.verbose:
                print("Generated files:")
                for file_type, file_path in results.items():
                    if isinstance(file_path, str):
                        print(f"  {file_type}: {file_path}")
                        
        except ImportError as e:
            raise MD2PPTError(f"Video export dependencies not available: {e}")
        except Exception as e:
            raise MD2PPTError(f"Failed to generate video: {e}")
    
    def _convert_all_formats(self, input_path: Path, output_path: Path, args) -> None:
        """Convert to all supported formats."""
        base_name = output_path.stem
        output_dir = output_path.parent
        
        formats = [
            ('pptx', f"{base_name}.pptx"),
            ('html', f"{base_name}.html"),
            ('video', f"{base_name}.mp4")
        ]
        
        for format_type, filename in formats:
            try:
                # Update args for each format
                format_args = args.__class__(**vars(args))
                format_args.format = format_type
                
                format_output = output_dir / filename
                self._convert_file(input_path, format_output, format_args)
                
                if args.verbose:
                    print(f"✅ Generated {format_type}: {format_output}")
                    
            except Exception as e:
                print(f"❌ Failed to generate {format_type}: {e}")
                continue
    
    def _start_api_server(self, args) -> int:
        """Start the API server."""
        try:
            import uvicorn
            from api.app import app
            
            host = "0.0.0.0"
            port = 8000
            
            print(f"Starting API server on {host}:{port}")
            print(f"API documentation available at http://{host}:{port}/docs")
            
            uvicorn.run(app, host=host, port=port)
            return 0
        except ImportError:
            print("Error: API dependencies not installed. Install with: pip install -e .[api]", file=sys.stderr)
            return 1
        except Exception as e:
            print(f"Error starting API server: {e}", file=sys.stderr)
            return 1
    
    def _start_mcp_server(self, args) -> int:
        """Start the MCP server."""
        try:
            import asyncio
            import subprocess
            import sys
            
            print("Starting MCP server...")
            # Run the MCP server script directly
            result = subprocess.run([
                sys.executable, "-c", 
                "import asyncio; "
                "import mcp.server.stdio; "
                "from mcp.server import server; "
                "asyncio.run(mcp.server.stdio.stdio_server(server))"
            ])
            return result.returncode
        except ImportError:
            print("Error: MCP dependencies not installed. Install with: pip install -e .[mcp]", file=sys.stderr)
            return 1
        except Exception as e:
            print(f"Error starting MCP server: {e}", file=sys.stderr)
            return 1


def main() -> int:
    """Main entry point for the CLI."""
    cli = CLICommands()
    return cli.run()